/**********************************************
*  Classes:   CdnD3d9Renderer
*  Desc:      Renders geometry using Direct3D 9.
*             Singleton class - inherits from 
*		      CdnRenderer.
*  Author:    Vaios Kalpias-Ilias (C) 2008-2009
***********************************************/

#ifndef CDND3D9RENDERER_H
#define CDND3D9RENDERER_H

#include "CdnRenderer.h"
#include <map>
#include <d3d9.h>

class Light;
SmartPointer(Light);

class CdnD3d9Renderer : public CdnRenderer
{
	friend class CdnRenderer;

public:

	// initializes renderer
	bool Init(HINSTANCE &hInstance, 
		bool fullscreen = false,
		int width = 1024,
		int height = 768,
		const char* title = "CodenWindow");

	// render a scene graph
	void RenderScene (SceneNode* scene);
	// creates vertices, normals etc for a node
	bool BindNodeToMesh(GeometryNode* node,
		mth::Vector3* vertices,
		mth::Vector3* normals,
		mth::Vector2* texCoords,
		int numOfVertices);

	// gets a texture id
	unsigned int GetNewTextureId(){return 1;}

	// sets a texture's environment state
	void SetTextureEnvState(unsigned int texId,
		TextureProperty::EnvironmentState state);

	// resizes window
	void ResizeWindow(int width, int height);

	// deletes geometry resources
	void UnloadGeometry();

	void SetSkyBox (SkyBoxPtr skyBox){};

private:

	typedef std::list <GeometryNode*> GeometryList;
	typedef std::map <unsigned int, GeometryList*> GeometryMap;
	typedef std::map <MaterialProperty*, GeometryMap*> MaterialMap;
	typedef std::map <TextureProperty*, MaterialMap* > TexturesMap;

	// the pointer to our Direct3D interface
	LPDIRECT3D9 m_D3d;    
	 // the pointer to the device class
	LPDIRECT3DDEVICE9 m_D3dDevice;   


	// struct used to represent vertices
	
	typedef struct d3dVert_t
	{
		float x;
		float y;
		float z;
		DWORD xrgb;
	} D3dVertex;
	

	// struct used to render vbo's
	typedef struct render_t
	{
		unsigned int verticesName;
		unsigned int normalsName;
		unsigned int texCoordsName;
		unsigned int numOfVertices;
		LPDIRECT3DVERTEXBUFFER9 pBuffer;

		render_t()
			: verticesName(0),
			normalsName(0),
			texCoordsName(0),
			numOfVertices(0),
			pBuffer(0)
		{}

		render_t(unsigned int vertName,
			unsigned int normName,
			unsigned int texName,
			unsigned int num,
			IDirect3DVertexBuffer9* pBuf)
			: verticesName(vertName),
			normalsName(normName),
			texCoordsName(texName),
			numOfVertices(num),
			pBuffer(pBuf)
		{}

	} RenderStruct;

	// list of renderstructs to be rendered
	typedef std::list<RenderStruct*> RenderList;
	RenderList m_lRenderStructs;

	// sorted geometry
	TexturesMap m_SortedGeometry;

	// ctor - dtor
	CdnD3d9Renderer();
	~CdnD3d9Renderer();

	// destroys current window
	void DestroyRenderWindow();

	// creates window
	bool CreateRendererWindow(HINSTANCE &hInstance, 
		bool fullscreen,
		int width,
		int height,
		const char* title);

	// sorts scene by states
	void SortScene(SceneNode* scene);
	// rendered sorted geometry
	void RenderSorted();
	// clears sorted geometry
	void ClearSorted();
	// enable vertices
	void EnableVertices(GeometryNode* node);
	// disable vertices
	void DisableVertices(GeometryNode* node);
	// enable normals
	void EnableNormals(GeometryNode* node);
	// disable normals
	void DisableNormals(GeometryNode* node);
	// enable texture coords
	void EnableTexCoords(GeometryNode* node);
	// disable tex coords
	void DisableTexCoords(GeometryNode* node);
	// enable textures
	void EnableTextures(TextureProperty* tex);
	// enable material
	void EnableMaterial(MaterialProperty* mat);
	// enables all lights for a node
	void EnableLights(GeometryNode* node);
	// enables one of 8 lights
	void EnableLight(LightPtr light, unsigned int num);
	// disables lights
	void DisableLights();
	// show bounding boxes
	void ShowBoundingBoxes(GeometryNode* node);
};

#endif